package cs236369.webserver.classes;

import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.Map;

import Logging.Monitor;

import cs236369.webserver.typehandler.Session;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtNewMethod;
import javassist.NotFoundException;

public class CreateClass {

	private StringBuilder commands = new StringBuilder();
	private final CtClass evalClass;
	private final String className;
	
	public CreateClass(String pathname,String className) throws NotFoundException {
		
		ClassPool pool = ClassPool.getDefault();
		// to make our newly created classes will be found
		pool.insertClassPath("../../../");
		pool.insertClassPath(new ClassClassPath(this.getClass()));
		// adding the classpath
		pool.insertClassPath(pathname);

		this.className = className;
		evalClass = pool.makeClass(this.className);

	}
	
	public void addCommandToMethod(String command) {
		Monitor.write(this, "We added the following command:"+command);
		commands.append(command);
	}
	
	
	/**
	 * Adds the current content of the message to the class
	 */
	public void addMethod() throws Exception {
		
		// adding the method to the class
		evalClass.addMethod(
				CtNewMethod.make(	
								"public void generate (" +
								 "java.util.Map params," +
								 "java.io.PrintStream  out," +
								 "cs236369.webserver.typehandler.Session session) {" + 
								 commands + "}", evalClass));

	}
	
	/**
	 * 
	 * @param params the parameters passes should be in the same order as created
	 * . That order is the same as in the calling method.
	 * @throws Exception
	 */
	public void activateMehod(	Map<String,String> parameters, 
								PrintStream out,
								Session session) throws Exception {
		
		Monitor.write(this, "Created the class:"+className);
		// get a java.lang.Class object from Javassist's CtClass object
		Class createdClass = evalClass.toClass();

		// instantiate it
		Object obj = createdClass.newInstance();

		// get a handle to the method we added earlier
		Class[] formalParams = new Class[] { Map.class,PrintStream.class,Session.class };
		Method meth = createdClass.getDeclaredMethod("generate", formalParams);

		// call the method with parameters
		Monitor.write(this, "invoke the html generating method");
		meth.invoke(obj,parameters,out,session);
	}
	
}
